package com.fr.base;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;

public class ConcurrentHashMap extends AbstractMap
  implements Map, Cloneable, Serializable
{
  protected transient Entry[] table;
  protected static final int CONCURRENCY_LEVEL = 32;
  protected static final int SEGMENT_MASK = 31;
  protected final Segment[] segments;
  public static int DEFAULT_INITIAL_CAPACITY = 32;
  private static final int MINIMUM_CAPACITY = 32;
  private static final int MAXIMUM_CAPACITY = 1073741824;
  public static final float DEFAULT_LOAD_FACTOR = 0.75F;
  protected final float loadFactor;
  protected int threshold;
  protected volatile transient int votesForResize;
  protected transient Set keySet;
  protected transient Set entrySet;
  protected transient Collection values;

  protected static int bitcount(int paramInt)
  {
    paramInt -= ((0xAAAAAAAA & paramInt) >>> 1);
    paramInt = (paramInt & 0x33333333) + (paramInt >>> 2 & 0x33333333);
    paramInt = paramInt + (paramInt >>> 4) & 0xF0F0F0F;
    paramInt += (paramInt >>> 8);
    paramInt += (paramInt >>> 16);
    return (paramInt & 0xFF);
  }

  private int p2capacity(int paramInt)
  {
    int j;
    int i = paramInt;
    if ((i > 1073741824) || (i < 0))
    {
      j = 1073741824;
    }
    else
    {
      j = 32;
      while (j < i)
        j <<= 1;
    }
    return j;
  }

  protected static int hash(Object paramObject)
  {
    int i = paramObject.hashCode();
    return ((i << 7) - i + (i >>> 9) + (i >>> 17));
  }

  protected boolean eq(Object paramObject1, Object paramObject2)
  {
    return ((paramObject1 == paramObject2) || (paramObject1.equals(paramObject2)));
  }

  protected Entry[] newTable(int paramInt)
  {
    this.threshold = ((int)(paramInt * this.loadFactor / 32.0F) + 1);
    return new Entry[paramInt];
  }

  public ConcurrentHashMap(int paramInt, float paramFloat)
  {
    this.segments = new Segment[32];
    this.keySet = null;
    this.entrySet = null;
    this.values = null;
    if (paramFloat <= 0.0F)
      throw new IllegalArgumentException("Illegal Load factor: " + paramFloat);
    this.loadFactor = paramFloat;
    for (int i = 0; i < this.segments.length; ++i)
      this.segments[i] = new Segment();
    i = p2capacity(paramInt);
    this.table = newTable(i);
  }

  public ConcurrentHashMap(int paramInt)
  {
    this(paramInt, 0.75F);
  }

  public ConcurrentHashMap()
  {
    this(DEFAULT_INITIAL_CAPACITY, 0.75F);
  }

  public ConcurrentHashMap(Map paramMap)
  {
    this(Math.max((int)(paramMap.size() / 0.75F) + 1, 32), 0.75F);
    putAll(paramMap);
  }

  public int size()
  {
    int i = 0;
    for (int j = 0; j < this.segments.length; ++j)
      i += this.segments[j].getCount();
    return i;
  }

  public boolean isEmpty()
  {
    for (int i = 0; i < this.segments.length; ++i)
      if (this.segments[i].getCount() != 0)
        return false;
    return true;
  }

  public Object get(Object paramObject)
  {
    int i = hash(paramObject);
    Entry[] arrayOfEntry = this.table;
    int j = i & arrayOfEntry.length - 1;
    Entry localEntry1 = arrayOfEntry[j];
    for (Object localObject1 = localEntry1; localObject1 != null; localObject1 = ((Entry)localObject1).next)
      if ((((Entry)localObject1).hash == i) && (eq(paramObject, ((Entry)localObject1).key)))
      {
        localObject2 = ((Entry)localObject1).value;
        if (localObject2 == null)
          break;
        return localObject2;
      }
    Object localObject2 = this.segments[(i & 0x1F)];
    synchronized (localObject2)
    {
      arrayOfEntry = this.table;
      j = i & arrayOfEntry.length - 1;
      Entry localEntry2 = arrayOfEntry[j];
      if ((localObject1 == null) && (localEntry1 == localEntry2))
        break label178;
      for (localObject1 = localEntry2; localObject1 != null; localObject1 = ((Entry)localObject1).next)
        if ((((Entry)localObject1).hash == i) && (eq(paramObject, ((Entry)localObject1).key)))
          return ((Entry)localObject1).value;
      label178: return null;
    }
  }

  public boolean containsKey(Object paramObject)
  {
    return (get(paramObject) != null);
  }

  public Object put(Object paramObject1, Object paramObject2)
  {
    int j;
    Entry[] arrayOfEntry;
    int k;
    if (paramObject2 == null)
      throw new NullPointerException();
    int i = hash(paramObject1);
    Segment localSegment1 = this.segments[(i & 0x1F)];
    synchronized (localSegment1)
    {
      arrayOfEntry = this.table;
      int l = i & arrayOfEntry.length - 1;
      Entry localEntry1 = arrayOfEntry[l];
      for (Entry localEntry2 = localEntry1; localEntry2 != null; localEntry2 = localEntry2.next)
        if ((localEntry2.hash == i) && (eq(paramObject1, localEntry2.key)))
        {
          Object localObject1 = localEntry2.value;
          localEntry2.value = paramObject2;
          return localObject1;
        }
      localEntry2 = new Entry(i, paramObject1, paramObject2, localEntry1);
      arrayOfEntry[l] = localEntry2;
      if ((j = ++localSegment1.count) >= this.threshold)
        break label164;
      return null;
      label164: int i1 = 1 << (i & 0x1F);
      k = this.votesForResize;
      if ((k & i1) != 0)
        break label200;
      label200: k = this.votesForResize |= i1;
    }
    if ((bitcount(k) >= 8) || (j > this.threshold * 32))
      resize(0, arrayOfEntry);
    return null;
  }

  public Object putIfAbsent(Object paramObject1, Object paramObject2)
  {
    label115: int j;
    Entry[] arrayOfEntry;
    int k;
    if (paramObject2 == null)
      throw new NullPointerException();
    int i = hash(paramObject1);
    Segment localSegment1 = this.segments[(i & 0x1F)];
    synchronized (localSegment1)
    {
      arrayOfEntry = this.table;
      int l = i & arrayOfEntry.length - 1;
      Entry localEntry1 = arrayOfEntry[l];
      for (Entry localEntry2 = localEntry1; (localEntry2 != null) && (((localEntry2.hash != i) || (!(eq(paramObject1, localEntry2.key))))); localEntry2 = localEntry2.next);
      if (localEntry2 == null)
        break label115;
      Object localObject1 = localEntry2.value;
      return localObject1;
      localObject1 = null;
      Entry localEntry3 = new Entry(i, paramObject1, paramObject2, localEntry1);
      arrayOfEntry[l] = localEntry3;
      if ((j = ++localSegment1.count) >= this.threshold)
        break label166;
      return null;
      label166: int i1 = 1 << (i & 0x1F);
      k = this.votesForResize;
      if ((k & i1) != 0)
        break label202;
      label202: k = this.votesForResize |= i1;
    }
    if ((bitcount(k) >= 8) || (j > this.threshold * 32))
      resize(0, arrayOfEntry);
    return null;
  }

  protected void resize(int paramInt, Entry[] paramArrayOfEntry)
  {
    Segment localSegment1 = this.segments[paramInt];
    synchronized (localSegment1)
    {
      if (paramArrayOfEntry == this.table)
      {
        int i = paramInt + 1;
        if (i < this.segments.length)
          resize(i, paramArrayOfEntry);
        else
          rehash();
      }
    }
  }

  protected void rehash()
  {
    this.votesForResize = 0;
    Entry[] arrayOfEntry1 = this.table;
    int i = arrayOfEntry1.length;
    if (i >= 1073741824)
    {
      this.threshold = 2147483647;
      return;
    }
    int j = i << 1;
    Entry[] arrayOfEntry2 = newTable(j);
    int k = j - 1;
    for (int l = 0; l < i; ++l)
    {
      Entry localEntry3;
      int i3;
      Entry localEntry1 = arrayOfEntry1[l];
      if (localEntry1 != null)
      {
        int i1 = localEntry1.hash & k;
        Entry localEntry2 = localEntry1.next;
        if (localEntry2 == null)
        {
          arrayOfEntry2[i1] = localEntry1;
        }
        else
        {
          Object localObject = localEntry1;
          int i2 = i1;
          for (localEntry3 = localEntry2; localEntry3 != null; localEntry3 = localEntry3.next)
          {
            i3 = localEntry3.hash & k;
            if (i3 != i2)
            {
              i2 = i3;
              localObject = localEntry3;
            }
          }
          arrayOfEntry2[i2] = localObject;
          for (localEntry3 = localEntry1; localEntry3 != localObject; localEntry3 = localEntry3.next)
          {
            i3 = localEntry3.hash & k;
            arrayOfEntry2[i3] = new Entry(localEntry3.hash, localEntry3.key, localEntry3.value, arrayOfEntry2[i3]);
          }
        }
      }
    }
    this.table = arrayOfEntry2;
  }

  public Object remove(Object paramObject)
  {
    return remove(paramObject, null);
  }

  protected Object remove(Object paramObject1, Object paramObject2)
  {
    int i = hash(paramObject1);
    Segment localSegment1 = this.segments[(i & 0x1F)];
    synchronized (localSegment1)
    {
      Entry[] arrayOfEntry = this.table;
      int j = i & arrayOfEntry.length - 1;
      Entry localEntry1 = arrayOfEntry[j];
      Entry localEntry2 = localEntry1;
      while (true)
      {
        if (localEntry2 == null)
          return null;
        if ((localEntry2.hash == i) && (eq(paramObject1, localEntry2.key)))
          break;
        localEntry2 = localEntry2.next;
      }
      Object localObject1 = localEntry2.value;
      if ((paramObject2 == null) || (paramObject2.equals(localObject1)))
        break label118;
      return null;
      label118: localEntry2.value = null;
      Entry localEntry3 = localEntry2.next;
      for (Entry localEntry4 = localEntry1; localEntry4 != localEntry2; localEntry4 = localEntry4.next)
        localEntry3 = new Entry(localEntry4.hash, localEntry4.key, localEntry4.value, localEntry3);
      arrayOfEntry[j] = localEntry3;
      localSegment1.count -= 1;
      return localObject1;
    }
  }

  public boolean containsValue(Object paramObject)
  {
    if (paramObject == null)
      throw new NullPointerException();
    for (Segment localSegment1 = 0; localSegment1 < this.segments.length; ++localSegment1)
    {
      Entry[] arrayOfEntry;
      Segment localSegment2 = this.segments[localSegment1];
      synchronized (localSegment2)
      {
        arrayOfEntry = this.table;
      }
      ??? = localSegment1;
      while (??? < arrayOfEntry.length)
      {
        int i;
        for (Entry localEntry = arrayOfEntry[???]; localEntry != null; localEntry = localEntry.next)
          if (paramObject.equals(localEntry.value))
            return true;
        ??? += this.segments.length;
      }
    }
    return false;
  }

  public boolean contains(Object paramObject)
  {
    return containsValue(paramObject);
  }

  public void putAll(Map paramMap)
  {
    int i = paramMap.size();
    if (i == 0)
      return;
    while (true)
    {
      int j;
      synchronized (this.segments[0])
      {
        localObject1 = this.table;
        j = this.threshold * 32;
      }
      if (i < j)
        break;
      resize(0, localObject1);
    }
    Object localObject1 = paramMap.entrySet().iterator();
    while (((Iterator)localObject1).hasNext())
    {
      Map.Entry localEntry = (Map.Entry)((Iterator)localObject1).next();
      put(localEntry.getKey(), localEntry.getValue());
    }
  }

  public void clear()
  {
    for (int i = 0; i < this.segments.length; ++i)
    {
      Segment localSegment1 = this.segments[i];
      synchronized (localSegment1)
      {
        Entry[] arrayOfEntry = this.table;
        int j = i;
        while (j < arrayOfEntry.length)
        {
          for (Entry localEntry = arrayOfEntry[j]; localEntry != null; localEntry = localEntry.next)
            localEntry.value = null;
          arrayOfEntry[j] = null;
          localSegment1.count = 0;
          j += this.segments.length;
        }
      }
    }
  }

  public Object clone()
  {
    return new ConcurrentHashMap(this);
  }

  public Set keySet()
  {
    Set localSet = this.keySet;
    return (this.keySet = new KeySet(this, null));
  }

  public Collection values()
  {
    Collection localCollection = this.values;
    return (this.values = new Values(this, null));
  }

  public Set entrySet()
  {
    Set localSet = this.entrySet;
    return (this.entrySet = new EntrySet(this, null));
  }

  public Enumeration keys()
  {
    return new KeyIterator(this);
  }

  public Enumeration elements()
  {
    return new ValueIterator(this);
  }

  private void writeObject(ObjectOutputStream paramObjectOutputStream)
    throws IOException
  {
    int i;
    paramObjectOutputStream.defaultWriteObject();
    synchronized (this.segments[0])
    {
      i = this.table.length;
    }
    paramObjectOutputStream.writeInt(i);
    for (Segment localSegment2 = 0; localSegment2 < this.segments.length; ++localSegment2)
    {
      Entry[] arrayOfEntry;
      Segment localSegment3 = this.segments[localSegment2];
      synchronized (localSegment3)
      {
        arrayOfEntry = this.table;
      }
      ??? = localSegment2;
      while (??? < arrayOfEntry.length)
      {
        int j;
        for (Entry localEntry = arrayOfEntry[???]; localEntry != null; localEntry = localEntry.next)
        {
          paramObjectOutputStream.writeObject(localEntry.key);
          paramObjectOutputStream.writeObject(localEntry.value);
        }
        ??? += this.segments.length;
      }
    }
    paramObjectOutputStream.writeObject(null);
    paramObjectOutputStream.writeObject(null);
  }

  private void readObject(ObjectInputStream paramObjectInputStream)
    throws IOException, ClassNotFoundException
  {
    paramObjectInputStream.defaultReadObject();
    int i = paramObjectInputStream.readInt();
    this.table = newTable(i);
    for (int j = 0; j < this.segments.length; ++j)
      this.segments[j] = new Segment();
    while (true)
    {
      Object localObject1 = paramObjectInputStream.readObject();
      Object localObject2 = paramObjectInputStream.readObject();
      if (localObject1 == null)
        return;
      put(localObject1, localObject2);
    }
  }

  protected class ValueIterator extends ConcurrentHashMap.HashIterator
  {
    private final ConcurrentHashMap this$0;

    protected ValueIterator()
    {
      super(paramConcurrentHashMap);
      this.this$0 = paramConcurrentHashMap;
    }

    protected Object returnValueOfNext()
    {
      return this.currentValue;
    }
  }

  protected class KeyIterator extends ConcurrentHashMap.HashIterator
  {
    private final ConcurrentHashMap this$0;

    protected KeyIterator()
    {
      super(paramConcurrentHashMap);
      this.this$0 = paramConcurrentHashMap;
    }

    protected Object returnValueOfNext()
    {
      return this.currentKey;
    }
  }

  protected class HashIterator
    implements Iterator, Enumeration
  {
    protected final ConcurrentHashMap.Entry[] tab;
    protected int index;
    protected ConcurrentHashMap.Entry entry;
    protected Object currentKey;
    protected Object currentValue;
    protected ConcurrentHashMap.Entry lastReturned;
    private final ConcurrentHashMap this$0;

    protected HashIterator()
    {
      this.this$0 = paramConcurrentHashMap;
      this.entry = null;
      this.lastReturned = null;
      synchronized (paramConcurrentHashMap.segments[0])
      {
        this.tab = paramConcurrentHashMap.table;
      }
      for (int i = 1; i < paramConcurrentHashMap.segments.length; ++i)
        paramConcurrentHashMap.segments[i].synch();
      this.index = (this.tab.length - 1);
    }

    public boolean hasMoreElements()
    {
      return hasNext();
    }

    public Object nextElement()
    {
      return next();
    }

    public boolean hasNext()
    {
      do
      {
        if (this.entry != null)
        {
          Object localObject = this.entry.value;
          if (localObject != null)
          {
            this.currentKey = this.entry.key;
            this.currentValue = localObject;
            return true;
          }
        }
        for (this.entry = this.entry.next; (this.entry == null) && (this.index >= 0); this.entry = this.tab[(this.index--)]);
      }
      while (this.entry != null);
      this.currentKey = (this.currentValue = null);
      return false;
    }

    protected Object returnValueOfNext()
    {
      return this.entry;
    }

    public Object next()
    {
      if ((this.currentKey == null) && (!(hasNext())))
        throw new NoSuchElementException();
      Object localObject = returnValueOfNext();
      this.lastReturned = this.entry;
      this.currentKey = (this.currentValue = null);
      this.entry = this.entry.next;
      return localObject;
    }

    public void remove()
    {
      if (this.lastReturned == null)
        throw new IllegalStateException();
      this.this$0.remove(this.lastReturned.key);
      this.lastReturned = null;
    }
  }

  protected static class Entry
    implements Map.Entry
  {
    protected final Object key;
    protected volatile Object value;
    protected final int hash;
    protected final Entry next;

    Entry(int paramInt, Object paramObject1, Object paramObject2, Entry paramEntry)
    {
      this.value = paramObject2;
      this.hash = paramInt;
      this.key = paramObject1;
      this.next = paramEntry;
    }

    public Object getKey()
    {
      return this.key;
    }

    public Object getValue()
    {
      return this.value;
    }

    public Object setValue(Object paramObject)
    {
      if (paramObject == null)
        throw new NullPointerException();
      Object localObject = this.value;
      this.value = paramObject;
      return localObject;
    }

    public boolean equals(Object paramObject)
    {
      if (!(paramObject instanceof Map.Entry))
        return false;
      Map.Entry localEntry = (Map.Entry)paramObject;
      return ((this.key.equals(localEntry.getKey())) && (this.value.equals(localEntry.getValue())));
    }

    public int hashCode()
    {
      return (this.key.hashCode() ^ this.value.hashCode());
    }

    public String toString()
    {
      return this.key + "=" + this.value;
    }
  }

  private class EntrySet extends AbstractSet
  {
    private final ConcurrentHashMap this$0;

    private EntrySet()
    {
      this.this$0 = paramConcurrentHashMap;
    }

    public Iterator iterator()
    {
      return new ConcurrentHashMap.HashIterator(this.this$0);
    }

    public boolean contains()
    {
      if (!(paramObject instanceof Map.Entry))
        return false;
      Map.Entry localEntry = (Map.Entry)paramObject;
      Object localObject = this.this$0.get(localEntry.getKey());
      return ((localObject != null) && (localObject.equals(localEntry.getValue())));
    }

    public boolean remove()
    {
      if (!(paramObject instanceof Map.Entry))
        return false;
      Map.Entry localEntry = (Map.Entry)paramObject;
      return (this.this$0.remove(localEntry.getKey(), localEntry.getValue()) != null);
    }

    public int size()
    {
      return this.this$0.size();
    }

    public void clear()
    {
      this.this$0.clear();
    }

    EntrySet(, ConcurrentHashMap.1 param1)
    {
      this(paramConcurrentHashMap);
    }
  }

  private class Values extends AbstractCollection
  {
    private final ConcurrentHashMap this$0;

    private Values()
    {
      this.this$0 = paramConcurrentHashMap;
    }

    public Iterator iterator()
    {
      return new ConcurrentHashMap.ValueIterator(this.this$0);
    }

    public int size()
    {
      return this.this$0.size();
    }

    public boolean contains()
    {
      return this.this$0.containsValue(paramObject);
    }

    public void clear()
    {
      this.this$0.clear();
    }

    Values(, ConcurrentHashMap.1 param1)
    {
      this(paramConcurrentHashMap);
    }
  }

  private class KeySet extends AbstractSet
  {
    private final ConcurrentHashMap this$0;

    private KeySet()
    {
      this.this$0 = paramConcurrentHashMap;
    }

    public Iterator iterator()
    {
      return new ConcurrentHashMap.KeyIterator(this.this$0);
    }

    public int size()
    {
      return this.this$0.size();
    }

    public boolean contains()
    {
      return this.this$0.containsKey(paramObject);
    }

    public boolean remove()
    {
      return (this.this$0.remove(paramObject) != null);
    }

    public void clear()
    {
      this.this$0.clear();
    }

    KeySet(, ConcurrentHashMap.1 param1)
    {
      this(paramConcurrentHashMap);
    }
  }

  protected static final class Segment
    implements Serializable
  {
    protected int count;

    protected synchronized int getCount()
    {
      return this.count;
    }

    protected synchronized void synch()
    {
    }
  }
}